/* Test.js
 *
 * Copyright 2006, Tim Dwelle.
 *
 * Licensed under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in
 * compliance with the License.  You may obtain a copy of
 * the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in
 * writing, software distributed under the License is
 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 * CONDITIONS OF ANY KIND, either express or implied.  See
 * the License for the specific language governing
 * permissions and limitations under the License.
 *
 */

$package("dowry.test");

/**
 * A baseclass for unit tests to be run via the TestRunner.
 *
 */
$class("Test").$as(
{
	_currentTest : {},

	/**
	 * Asserts the specified expression.
	 *
	 * @param expr  the boolean expression that is expected
	 *              to evaluate to true
	 *
	 * @param msg   (optional) the message to display if
	 *              the assertion fails
	 *
	 */
	assert: function(expr, msg)
	{
		if (msg == null)
		{
			msg = "assert: got " + expr;
		}

		try
		{
			if (expr)
			{
				this._pass();
			}
			else
			{
				this._fail(msg);
			}
		}
		catch(e)
		{
			this._error(e);
		}
	},

	/**
	 * Asserts that the expected value is equal to the
	 * actual value.
	 *
	 " @param actual    the actual value
	 *
	 * @param expected  the expected value
	 *
	 * @param msg       (optional) the message to display if
	 *                  the assertion fails
	 *
	 */
	assertEqual: function(actual, expected, msg)
	{
		if (msg == null)
		{
			msg = "assertEqual: expected " + expected + ", actual " + actual;
		}

		this.assert(expected == actual, msg);
	},

	/**
	 * Asserts that the expected value and actual value are
	 * not equal.
	 *
	 * @param actual    the actual value
	 *
	 * @param expected  the expected value
	 *
	 * @param msg       (optional) the message to display if
	 *                  the assertion fails
	 *
	 */
	assertNotEqual : function(actual, expected, msg)
	{
		if (msg == null)
		{
			msg = "assertNotEqual: got " + actual;
		}

		this.assert(expected != actual, msg);
	},

	/**
	 * Asserts that the provided value is null.
	 *
	 * @param obj   the provided value
	 *
	 * @param msg   (optional) the message to display if
	 *              the assertion fails
	 *
	 */
	assertNull : function(obj, msg)
	{
		if (msg == null)
		{
			msg = "assertNull: got " + obj;
		}

		this.assert(obj == null, msg);
	},

	/**
	 * Asserts that the provided value is not null.
	 *
	 * @param obj   the provided value
	 *
	 * @param msg   (optional) the message to display if
	 *              the assertion fails
	 *
	 */
	assertNotNull : function(obj, msg)
	{
		if (msg == null)
		{
			msg = "assertNotNull: got " + obj;
		}

		this.assert(obj != null, msg);
	},

	/**
	 * Instructs the test to wait for the specified
	 * duration, after which time to continue testing by
	 * executing the provided function.
	 *
	 * @param duration  the duration in milliseconds to wait
	 *
	 * @param func      the function to call when the wait
	 *                  has ended
	 *
	 */
	wait : function(duration, func)
	{
		this._currentTest.isWaiting = true;
		this._currentTest.func = func;
		this._currentTest.timeToWait = duration;
	},

	/**
	 * Handles a successful assertion.
	 *
	 */
	_pass : function()
	{
	    this._currentTest.assertions++;
	},

	/**
	 * Handles a failed assertion.
	 *
	 * @param msg   the message associated with this failure
	 *
	 */
	_fail : function(msg)
	{
		this._currentTest.failures++;
		var msgs = this._currentTest.messages;

		if (msgs != null)
		{
			msgs = msgs[msgs.length] = "FAILURE: " + msg;
		}
	},

	/**
	 * Handles an exception being thrown.
	 *
	 * @param err   the error object
	 *
	 */
	_error: function(err)
	{
		this._currentTest.errors++;
		var msgs = this._currentTest.messages;

		if (msgs != null)
		{
			msgs[msgs.length] = "ERROR:";
			for (var name in err)
			{
				msgs[msgs.length] = name+":"+err[name];
			}
		}
	}
});